Expand description
§vergen - Emit cargo instructions from a build script
vergen
, when used in conjunction with cargo build scripts can emit the following:
- Will emit
cargo:rustc-env=VAR=VALUE
for each feature you have enabled. These can be referenced with the env! macro in your code. - Will emit
cargo:rerun-if-changed=.git/HEAD
if the git feature is enabled. This is done to ensure any git instructions are regenerated when commits are made. - Will emit
cargo:rerun-if-changed=.git/<path_to_ref>
if the git feature is enabled. This is done to ensure any git instructions are regenerated when commits are made. - Can emit
cargo:warning
outputs if thefail_on_error
feature is not enabled and the requested variable is defaulted through error or theidempotent
flag. - Will emit
cargo:rerun-if-changed=build.rs
to rerun instruction emission if thebuild.rs
file changed. - Will emit
cargo:rerun-if-env-changed=VERGEN_IDEMPOTENT
to rerun instruction emission if theVERGEN_IDEMPOTENT
environment variable has changed. - Will emit
cargo:rerun-if-env-changed=SOURCE_DATE_EPOCH
to rerun instruction emission if theSOURCE_DATE_EPOCH
environment variable has changed.
§Usage
- Ensure you have build scripts enabled via the
build
configuration in yourCargo.toml
[package]
#..
build = "build.rs"
- Add
vergen
as a build dependency inCargo.toml
, specifying the features you wish to enable.
[dependencies]
#..
[build-dependencies]
# All features enabled
vergen = { version = "8.0.0", features = ["build", "cargo", "git", "gitcl", "rustc", "si"] }
# or
vergen = { version = "8.0.0", features = ["build", "git", "gitcl"] }
# if you wish to disable certain features
- Create a
build.rs
file that usesvergen
to emit cargo instructions. Configuration starts withEmitBuilder
. Eventually you will callemit
to output the cargo instructions. See theemit
documentation for more robust examples.
§Generate all output
use anyhow::Result;
use vergen::EmitBuilder;
pub fn main() -> Result<()> {
// NOTE: This will output everything, and requires all features enabled.
// NOTE: See the EmitBuilder documentation for configuration options.
EmitBuilder::builder()
.all_build()
.all_cargo()
.all_git()
.all_rustc()
.all_sysinfo()
.emit()?;
Ok(())
}
§Generate specific output
use anyhow::Result;
use vergen::EmitBuilder;
pub fn main() -> Result<()> {
// NOTE: This will output only a build timestamp and long SHA from git.
// NOTE: This set requires the build and git features.
// NOTE: See the EmitBuilder documentation for configuration options.
EmitBuilder::builder()
.build_timestamp()
.git_sha(false)
.emit()?;
Ok(())
}
- Use the
env!
macro in your code to read the environment variables.
println!("Build Timestamp: {}", env!("VERGEN_BUILD_TIMESTAMP"));
println!("git describe: {}", env!("VERGEN_GIT_DESCRIBE"));
§Features
vergen
has five main feature toggles allowing you to customize your output. No features are enabled by default.
You must specifically enable the features you wish to use.
Feature | Enables |
---|---|
build | VERGEN_BUILD_* instructions |
cargo | VERGEN_CARGO_* instructions |
git | VERGEN_GIT_* instructions and the cargo:rerun-if-changed instructions |
rustc | VERGEN_RUSTC_* instructions |
si | VERGEN_SYSINFO_* instructions |
§Configuring the git
feature
If you wish to use the git feature, you must also enable one of the git implementations.
The gitcl
features is lightweight, but depends on git
being on the path. The other
implementations allow for git instructions to be emitted without a reliance on
the git binary. The git2
library are bindings over
the libgit2
library, while gitoxide
is entirely implemented in Rust.
NOTE - These 3 features are mutually exclusive. Only one can be chosen. If you select
multiple, vergen
intentionally will not compile.
Features | Enables |
---|---|
gitcl | VERGEN_GIT_ instructions emitted via the git binary at the command line |
git2 | VERGEN_GIT_ instructions emitted via git git2 library |
gitoxide | VERGEN_GIT_ instructions emitted via the gitoxide library |
A common configuration would be as follows:
[build-dependencies]
vergen = { version = "8.0.0", features = [ "build", "git", "gitcl" ]}
# ...
§Cargo
feature unification for vergen
versions prior to 8.3.0
When a dependency is used by multiple packages, Cargo will use the union of all features enabled on that dependency when building it. Prior to version 8.3.0, vergen
had a set of mutually exclusive features gitcl
, git2
, and gitoxide
to enable to specific git backend you wished to use. If your crate has a dependency on another crate that uses vergen
, your crate may fail to compile if you select a different git
backend then the crate you depend on. For example, your crate depends on fancy-lib
.
§fancy-lib Cargo.toml
[build-dependencies]
vergen = { version = "8.2.10", features = ["git","gitcl"] }
§your crate Cargo.toml
[dependencies]
fancy-lib = "0.1.0"
[build-dependencies]
vergen = { version = "8.2.10", features = ["git","gitoxide"] }
Your crate will fail to compile because cargo
unifies this to
vergen = { version = "8.2.10", features = ["git","gitcl","gitoxide"] }
and prior to 8.3.0 vergen
will not compile with both gitcl
and gitoxide
as features.
As a workaround, you can use cargo tree -f "{p} {f}" | grep vergen
to determine the feature list cargo has set for vergen
. If
a git
backend has already been determined you will be able to use that without declaring those features in your dependency list. This is not perfect
as this leaves you at the mercy of your dependency and the git feature they selected, but it’s a workaround until version 9 comes out.
§fancy-lib Cargo.toml
[build-dependencies]
vergen = { version = "8.2.10", features = ["git","gitcl"] }
§your crate Cargo.toml
[dependencies]
fancy-lib = "0.1.0"
[build-dependencies]
vergen = "8.2.10"
§Unified
vergen = { version = "8.2.10", features = ["git","gitcl"] }
§Cargo
feature unification for vergen
versions 8.3.0 and beyond
vergen
will accept gitcl
,git2
, and gitoxide
as features. If more than one of them is included, vergen
will select gitcl
before git2
and git2
before gitoxide
.
§Environment Variables
vergen
currently recognizes the following environment variables
Variable | Functionality |
---|---|
VERGEN_IDEMPOTENT | If this environment variable is set vergen will use the idempotent output feature regardless of the configuration set in build.rs . This exists mainly to allow package maintainers to force idempotent output to generate deterministic binary output. |
SOURCE_DATE_EPOCH | If this environment variable is set vergen will use the value (unix time since epoch) as the basis for a time based instructions. This can help emit deterministic instructions. |
VERGEN_BUILD_* | If this environment variable is set vergen will use the value you specify for the output rather than generating it. |
VERGEN_CARGO_* | If this environment variable is set vergen will use the value you specify for the output rather than generating it. |
VERGEN_GIT_* | If this environment variable is set vergen will use the value you specify for the output rather than generating it. |
VERGEN_RUSTC_* | If this environment variable is set vergen will use the value you specify for the output rather than generating it. |
VERGEN_SYSINFO_* | If this environment variable is set vergen will use the value you specify for the output rather than generating it. |
§Goals
I initially wrote vergen
(version generator, so original) so I could embed a some git information in my
personal projects. Now, usage has grown to the point that vergen
needs to fit better in the rust ecosystem.
The current goals are as follows:
§Minimize the tool footprint
- Adopt an opt-in, rather than opt-out strategy for the features. The default feature set is empty and no instructions will be emitted.
- The instructions you have configured will be emitted. If there are errors or idempotentcy has been configured, some of those instructions may be defaulted.
- Allow overriding configurtion set in
build.rs
through environment variables. This will allow package maintainers to force sane defaults when packaging rust binaries for distribution.
§Minimize the compile time impact
git2
andgitoxide
are large features. These are opt-in now. I’ve also added back support for generating git instructions via thegit
binary.- I’ve removed some extraneous libraries. Any libraries added in the future will be checked against the current standard compile times to ensure the impact is not too great.
vergen
should compile and test from a source tarball.
§Support deterministic output
Compilations run from the same source oftentimes need to generate identical binaries. vergen
now supports
this determinism in a few ways.
- An
idempotent
configuration option has been added. When this is enabled in a build script, each build via cargo against the same source code should generate identical binaries. Instructions that output information that may change between builds (i.e. timestamps, sysinfo) will be defaulted. - Recognize common environment variables that support deterministic builds (i.e.
SOURCE_DATE_EPOCH
) - Allow
build.rs
configuration overrides though environment variables to allow users building a binary, but not controlling the source to generate deterministic binaries.
§Use Cases
I generally use vergen for the following two cases
- Generating verbose output describing a command line application.
~/p/r/app λ app -vv
app 0.1.0
Build Timestamp: 2021-02-23T20:14:46.558472672+00:00
Describe: 0.1.0-9-g46f83e1
Commit SHA: 46f83e112520533338245862d366f6a02cef07d4
Commit Date: 2021-02-23T08:08:02-05:00
Commit Branch: master
rustc Version: 1.52.0-nightly
rustc Channel: nightly
rustc Host Triple: x86_64-unknown-linux-gnu
rustc Commit SHA: 3f5aee2d5241139d808f4fdece0026603489afd1
cargo Target Triple: x86_64-unknown-linux-musl
cargo Profile: release
- Information endpoints in web apis
~/p/r/app λ curl https://some.app.com/info | jq
{
"build_timestamp": "2021-02-19T21:32:22.932833758+00:00",
"git_describe": "0.0.0-7-gc96c096",
"git_sha": "c96c0961c3b7b749eab92f6f588b67915889c4cd",
"git_commit_date": "2021-02-19T16:29:06-05:00",
"git_branch": "master",
"rustc_semver": "1.52.0-nightly",
"rustc_channel": "nightly",
"rustc_host_triple": "x86_64-unknown-linux-gnu",
"rustc_commit_sha": "3f5aee2d5241139d808f4fdece0026603489afd1",
"cargo_target_triple": "x86_64-unknown-linux-musl",
"cargo_profile": "release"
}
Structs§
- Used to determine what you want to refresh specifically on the
Cpu
type. - Build the
vergen
configuration to enable specific cargo instruction output - Used to determine which memory you want to refresh specifically.
- Used to determine what you want to refresh specifically on the
Process
type. - Used to determine what you want to refresh specifically on the
System
type.
Enums§
- DependencyKind
cargo
Dependencies can come in three kinds